/**
 * Copyright (c) 2007, Blue Hole Software. All rights reserved.
 * Code licensed under the Apache 2.0 License:
 * http://www.apache.org/licenses/
 */
package org.bhf.security.common;

import javax.security.auth.Subject;
import java.io.Serializable;
import java.security.Permission;
import java.security.Principal;

/**
 * A <code>PermissionPrincipal</code> is assigned at authentication time and carried in the <code>Subject</code> as
 * a <code>Principal</code>, in contrast to a static <code>Permission</code> that is assigned within a policy.
 */
public final class PermissionPrincipal implements Principal, Serializable
{
    private static final long                       serialVersionUID    = 7930732926638008763L;
    private static final Class<PermissionPrincipal> THIS_CLASS          = PermissionPrincipal.class;
    private static final PermissionPrincipal[]      NO_ROLES            = new PermissionPrincipal[0];

    /** Contained Permission */
    private final Permission permission;

    /**
     * Create a <code>DenyPermission</code> with the given <code>Permission</code>.
     * @param permission the denied <code>Permission</code>.
     *      Must not be <code>null</code>.
     * @throws java.lang.IllegalArgumentException if <code>permission == null</code>.
     */
    public                  PermissionPrincipal( final Permission permission )
    {
        if( permission == null )
            throw new IllegalArgumentException( "permission == null" );

        this.permission = permission;
    }

    /**
     * The <code>Principal</code> name is taken as the <code>toString()</code> of the contained
     * <code>Permission</code>.
     * @return The <code>Principal</code> name.
     */
    public String           getName()
    {
        return permission.toString();
    }

    /**
     * Returns the name of this <code>Principle</code>.
     * @return the name of this <code>Principle</code>.
     */
    public Permission       getPermission()
    {
        return permission;
    }

    /**
     * Returns the hash code based on the <code>Permission</code> hash code.
     * @return the hash code.
     */
    public int              hashCode()
    {
        return permission.hashCode();
    }

    /**
     * Equality based on contained <code>Permission</code>.
     * @param o Object against which to compare
     * @return <code>true</code> iff <code>o</code> is a <code>Role</code>
     *      with the same name.
     */
    public boolean          equals( final Object o )
    {
        try
        {
            return ((PermissionPrincipal)o).permission.equals( permission );
        }
        catch( Exception e )
        {
            return false;
        }
    }

    /**
     * Convenience method to return the <code>PermissionPrincipal</code>s in a
     * <code>Subject</code>.
     *
     * @param subject The <code>Subject</code> from which to extract the
     *      <code>PermissionPrincipal</code>s.  Must not be <code>null</code>.
     *
     * @throws java.lang.IllegalArgumentException if <code>subject == null</code>.
     *
     * @return The <code>PermissionPrincipal</code>s of the <code>Subject</code>.
     *      Guaranteed to not return <code>null</code> though may return
     *      an empty array.
     */
    public static PermissionPrincipal[] getPermissionPrincipal( final Subject subject )
    {
        if( subject == null )
            throw new IllegalArgumentException( "subject == null" );

        return subject.getPrincipals( THIS_CLASS ).toArray( NO_ROLES );
    }

    /**
     * Convenience method to return the <code>PermissionPrincipal</code>s of the
     * <code>Subject</code> associated with the current thread.
     *
     * @throws java.lang.IllegalArgumentException if there is no <code>Subject</code>
     *      associated with the current thread.
     *
     * @return The <code>PermissionPrincipal</code>s of the current <code>Subject</code>.
     *      Guaranteed to not return <code>null</code> though may return
     *      an empty array.
     */
    public static PermissionPrincipal[] getPermissionPrincipal()
    {
        return getPermissionPrincipal( ContextSubject.getContextSubject() );
    }
}


